def convert_gru(builder, layer, input_names, output_names, keras_layer):
    """
    Convert a GRU layer from keras to coreml.

    Parameters
    ----------
    keras_layer: layer
        A keras layer object.

    builder: NeuralNetworkBuilder
        A neural network builder object.
    """

    hidden_size = keras_layer.units
    input_size = keras_layer.input_shape[-1]

    output_all = keras_layer.return_sequences
    reverse_input = keras_layer.go_backwards

    # Keras: Z R O
    # CoreML: Z R O
    W_h, W_x, b = ([], [], [])
    keras_W_h = keras_layer.get_weights()[1].T
    W_h.append(keras_W_h[0 * hidden_size:][:hidden_size])
    W_h.append(keras_W_h[1 * hidden_size:][:hidden_size])
    W_h.append(keras_W_h[2 * hidden_size:][:hidden_size])

    keras_W_x = keras_layer.get_weights()[0].T
    W_x.append(keras_W_x[0 * hidden_size:][:hidden_size])
    W_x.append(keras_W_x[1 * hidden_size:][:hidden_size])
    W_x.append(keras_W_x[2 * hidden_size:][:hidden_size])

    if keras_layer.use_bias:
        keras_b = keras_layer.get_weights()[2]
        b.append(keras_b[0 * hidden_size:][:hidden_size])
        b.append(keras_b[1 * hidden_size:][:hidden_size])
        b.append(keras_b[2 * hidden_size:][:hidden_size])
    if len(b) == 0:
        b = None

    # Set actication type
    inner_activation_str = _get_recurrent_activation_name_from_keras(keras_layer.recurrent_activation)
    activation_str = _get_recurrent_activation_name_from_keras(keras_layer.activation)

    # Add to the network
    builder.add_gru(
       name = layer,
       W_h = W_h, W_x = W_x, b = b,
       input_size = input_size,
       hidden_size = hidden_size,
       input_names = input_names,
       output_names = output_names,
       activation = activation_str,
       inner_activation = inner_activation_str,
       output_all = output_all,
       reverse_input = reverse_input)