class_docstr: Gated Recurrent Unit (GRU) Layer.
  
  Parameters
  ----------
  {BaseRNNLayer.n_units}
  
  {BaseRNNLayer.only_return_final}
  
  input_weights : Initializer, ndarray
      Weight parameters for input connection.
      Defaults to :class:`HeNormal() <neupy.init.HeNormal>`.
  
  hidden_weights : Initializer, ndarray
      Weight parameters for hidden connection.
      Defaults to :class:`HeNormal() <neupy.init.HeNormal>`.
  
  biases : Initializer, ndarray
      Bias parameters for all gates.
      Defaults to :class:`Constant(0) <neupy.init.Constant>`.
  
  resetgate : function
      Activation function for the reset gate.
      Defaults to ``tf.nn.sigmoid``.
  
  updategate : function
      Activation function for the update gate.
      Defaults to ``tf.nn.sigmoid``.
  
  hidden_update : function
      Activation function for the hidden state update.
      Defaults to ``tf.tanh``.
  
  learn_init : bool
      If ``True``, make ``hidden_init`` trainable variable.
      Defaults to ``False``.
  
  hidden_init : array-like, Tensorfow variable, scalar or Initializer
      Initializer for initial hidden state (:math:`h_0`).
      Defaults to :class:`Constant(0) <neupy.init.Constant>`.
  
  backwards : bool
      If ``True``, process the sequence backwards and then reverse the
      output again such that the output from the layer is always
      from :math:`x_1` to :math:`x_n`. Defaults to ``False``.
  
  unroll_scan : bool
      If ``True`` the recursion is unrolled instead of using scan.
      For some graphs this gives a significant speed up but it
      might also consume more memory. When ``unroll_scan=True``,
      backpropagation always includes the full sequence, so
      ``n_gradient_steps`` must be set to ``-1`` and the input
      sequence length must be known at compile time (i.e.,
      cannot be given as ``None``). Defaults to ``False``.
  
  {BaseLayer.name}
  
  Notes
  -----
  Code was adapted from the
  `Lasagne <https://github.com/Lasagne/Lasagne>`_ library.
  
  Examples
  --------
  Sequence classification
  
  >>> from neupy.layers import *
  >>>
  >>> n_time_steps = 40
  >>> n_categories = 20
  >>> embedded_size = 10
  >>>
  >>> network = join(
  ...     Input(n_time_steps),
  ...     Embedding(n_categories, embedded_size),
  ...     GRU(20),
  ...     Sigmoid(1),
  ... )
  >>> network
  (?, 40) -> [... 4 layers ...] -> (?, 1)
code: def create_variables(self, input_shape):
      self.input_weights = self.variable(
          value=self.input_weights,
          name="input_weights",
          shape=(input_shape[-1], 3 * self.n_units),
      )
      self.hidden_weights = self.variable(
          value=self.hidden_weights,
          name="hidden_weights",
          shape=(self.n_units, 3 * self.n_units),
      )
      self.biases = self.variable(
          value=self.biases,
          name="biases",
          shape=(3 * self.n_units,),
      )
      self.hidden_init = self.variable(
          value=self.hidden_init,
          shape=(1, self.n_units),
          name="hidden_init",
          trainable=self.learn_init,
      )
  
imports: import types
  import tensorflow
  from neupy import init
  from neupy.utils import tensorflow_session
  from neupy.exceptions import LayerConnectionError
  from neupy.core.properties import IntProperty, Property, NumberProperty, ParameterProperty
  from .base import BaseLayer
label_desc: Use image node_id 2 for calling the GRU obj's underlying member method code with example usage: obj.create_variables(input_shape) without return types