import tensorflow as tf

      for ch in chars:
        output, state = cell(ch, state)
        outputs.append(output)
      # The outputs of this layer are the inputs of the subsequent layer.
      chars = tf.stack(outputs, axis=0)
      if training:
        chars = tf.nn.dropout(chars, self.keep_prob)
    # Extract the correct output (i.e., hidden state) for each example. All the
    # character sequences in this batch were padded to the same fixed length so
    # that they could be easily fed through the above RNN loop. The
    # `sequence_length` vector tells us the true lengths of the character
    # sequences, letting us obtain for each sequence the hidden state that was
    # generated by its non-padding characters.
    batch_range = [i for i in range(batch_size)]
    indices = tf.stack([sequence_length - 1, batch_range], axis=1)
    hidden_states = tf.gather_nd(chars, indices)
    return self.relu(hidden_states)


def loss(labels, predictions):
  """Computes mean squared loss."""
  return tf.reduce_mean(tf.squared_difference(predictions, labels))


def test(model, eval_data):
  """Computes the average loss on eval_data, which should be a Dataset."""
  avg_loss = tfe.metrics.Mean("loss")
  for (labels, chars, sequence_length) in tfe.Iterator(eval_data):
    predictions = model((chars, sequence_length), training=False)
    avg_loss(loss(labels, predictions))
