class_docstr: Echo State recurrent Network (ESN) cell.
  This implements the recurrent cell from the paper:
      H. Jaeger
      "The "echo state" approach to analysing and training recurrent neural networks".
      GMD Report148, German National Research Center for Information Technology, 2001.
      https://www.researchgate.net/publication/215385037
  
  Example:
  
  >>> inputs = np.random.random([30,23,9]).astype(np.float32)
  >>> ESNCell = tfa.rnn.ESNCell(4)
  >>> rnn = tf.keras.layers.RNN(ESNCell, return_sequences=True, return_state=True)
  >>> outputs, memory_state = rnn(inputs)
  >>> outputs.shape
  TensorShape([30, 23, 4])
  >>> memory_state.shape
  TensorShape([30, 4])
  
  Args:
      units: Positive integer, dimensionality in the reservoir.
      connectivity: Float between 0 and 1.
          Connection probability between two reservoir units.
          Default: 0.1.
      leaky: Float between 0 and 1.
          Leaking rate of the reservoir.
          If you pass 1, it is the special case the model does not have leaky
          integration.
          Default: 1.
      spectral_radius: Float between 0 and 1.
          Desired spectral radius of recurrent weight matrix.
          Default: 0.9.
      use_norm2: Boolean, whether to use the p-norm function (with p=2) as an upper
          bound of the spectral radius so that the echo state property is satisfied.
          It  avoids to compute the eigenvalues which has an exponential complexity.
          Default: False.
      use_bias: Boolean, whether the layer uses a bias vector.
          Default: True.
      activation: Activation function to use.
          Default: hyperbolic tangent (`tanh`).
      kernel_initializer: Initializer for the `kernel` weights matrix,
          used for the linear transformation of the inputs.
          Default: `glorot_uniform`.
      recurrent_initializer: Initializer for the `recurrent_kernel` weights matrix,
          used for the linear transformation of the recurrent state.
          Default: `glorot_uniform`.
      bias_initializer: Initializer for the bias vector.
          Default: `zeros`.
  Call arguments:
      inputs: A 2D tensor (batch x num_units).
      states: List of state tensors corresponding to the previous timestep.
code: def build(self, inputs_shape):
      input_size = tf.compat.dimension_value(
          tf.TensorShape(inputs_shape)[-1]
      )
      if input_size is None:
          raise ValueError(
              "Could not infer input size from inputs.get_shape()[-1]. Shape received is %s"
              % inputs_shape
          )
  
      def _esn_recurrent_initializer(shape, dtype, partition_info=None):
          recurrent_weights = tf.keras.initializers.get(
              self.recurrent_initializer
          )(shape, dtype)
  
          connectivity_mask = tf.cast(
              tf.math.less_equal(
                  tf.random.uniform(shape), self.connectivity
              ),
              dtype,
          )
          recurrent_weights = tf.math.multiply(
              recurrent_weights, connectivity_mask
          )
  
          # Satisfy the necessary condition for the echo state property `max(eig(W)) < 1`
          if self.use_norm2:
              # This condition is approximated scaling the norm 2 of the reservoir matrix
              # which is an upper bound of the spectral radius.
              recurrent_norm2 = tf.math.sqrt(
                  tf.math.reduce_sum(tf.math.square(recurrent_weights))
              )
              is_norm2_0 = tf.cast(
                  tf.math.equal(recurrent_norm2, 0), dtype
              )
              scaling_factor = tf.cast(self.spectral_radius, dtype) / (
                  recurrent_norm2 + 1 * is_norm2_0
              )
          else:
              abs_eig_values = tf.abs(
                  tf.linalg.eig(recurrent_weights)[0]
              )
              scaling_factor = tf.math.divide_no_nan(
                  tf.cast(self.spectral_radius, dtype),
                  tf.reduce_max(abs_eig_values),
              )
  
          recurrent_weights = tf.multiply(
              recurrent_weights, scaling_factor
          )
  
          return recurrent_weights
  
      self.recurrent_kernel = self.add_weight(
          name="recurrent_kernel",
          shape=[self.units, self.units],
          initializer=_esn_recurrent_initializer,
          trainable=False,
          dtype=self.dtype,
      )
      self.kernel = self.add_weight(
          name="kernel",
          shape=[input_size, self.units],
          initializer=self.kernel_initializer,
          trainable=False,
          dtype=self.dtype,
      )
  
      if self.use_bias:
          self.bias = self.add_weight(
              name="bias",
              shape=[self.units],
              initializer=self.bias_initializer,
              trainable=False,
              dtype=self.dtype,
          )
  
      self.built = True
  
file_path: addons/tensorflow_addons/rnn/esn_cell.py
imports: import tensorflow
  from typeguard import typechecked
  from tensorflow_addons.rnn.abstract_rnn_cell import AbstractRNNCell
  from tensorflow_addons.utils.types import Activation, Initializer
label_desc: Use image node_id 4 for calling the ESNCell obj's underlying member method code with example usage: obj.build(inputs_shape) and returns: recurrent_weights