From the Keras Docs:

merge_mode: Mode by which outputs of the forward and backward RNNs will be combined. One of {‘sum’, ‘mul’, ‘concat’, ‘ave’, None}. If None, the outputs will not be combined, they will be returned as a list. Default value is ‘concat’.

If I understand this correctly, this concerns only the merging of the last(!) layer of a Bi-RNN, and is therefore independent from the number of layers. This seems intuitive since merging the different layers does not seem that meaningful to me.
So when it comes to merging the forward and backward pass, you can do the following:
# Push through RNN layer
rnn_output, self.hidden = self.rnn(X, self.hidden)

# Extract last hidden state depending on the RNN type
if self.params.rnn_type == RnnType.GRU:
    final_state = self.hidden.view(self.params.num_layers, self.num_directions, batch_size, self.params.rnn_hidden_dim)[-1]
elif self.params.rnn_type == RnnType.LSTM:
    final_state = self.hidden[0].view(self.params.num_layers, self.num_directions, batch_size, self.params.rnn_hidden_dim)[-1]

# Handle directions
final_hidden_state = None
if self.num_directions == 1:    # RNN is unidirectional
    final_hidden_state = final_state.squeeze(0)
elif self.num_directions == 2:  # RNN is bidirectional
    h_1, h_2 = final_state[0], final_state[1]
    # final_hidden_state = h_1 + h_2               # Add both states (requires changes to the input size of first linear layer + attention layer)
    final_hidden_state = torch.cat((h_1, h_2), 1)  # Concatenate both states

(taken from my own code 5)