Creates an initial state consisting of trainable variables.

  The trainable variables are created with the same shapes as the elements of
  `state_size` and are tiled to produce an initial state.

  Args:
    batch_size: An int, or scalar int32 Tensor representing the batch size.
    state_size: A `TensorShape` or nested tuple of `TensorShape`s to use for the
        shape of the trainable variables.
    dtype: The data type used to create the variables and thus initial state.
    initializers: An optional container of the same structure as `state_size`
        containing initializers for the variables.
    regularizers: An optional container of the same structure as `state_size`
        containing regularizers for the variables.
    name: optional string used to prefix the initial state variable names.

  Returns:
    A `Tensor` or nested tuple of `Tensor`s with the same size and structure
    as `state_size`, where each `Tensor` is a tiled trainable `Variable`.

  Raises:
    ValueError: if the user passes initializers that are not functions.
    ValueError: if the user passes regularizers that are not functions.

def trainable_initial_state(batch_size, state_size, dtype, initializers=None,
                            regularizers=None, name=None):
  """Creates an initial state consisting of trainable variables.

  The trainable variables are created with the same shapes as the elements of
  `state_size` and are tiled to produce an initial state.

  Args:
    batch_size: An int, or scalar int32 Tensor representing the batch size.
    state_size: A `TensorShape` or nested tuple of `TensorShape`s to use for the
        shape of the trainable variables.
    dtype: The data type used to create the variables and thus initial state.
    initializers: An optional container of the same structure as `state_size`
        containing initializers for the variables.
    regularizers: An optional container of the same structure as `state_size`
        containing regularizers for the variables.
    name: optional string used to prefix the initial state variable names.

  Returns:
    A `Tensor` or nested tuple of `Tensor`s with the same size and structure
    as `state_size`, where each `Tensor` is a tiled trainable `Variable`.

  Raises:
    ValueError: if the user passes initializers that are not functions.
    ValueError: if the user passes regularizers that are not functions.
  """
  flat_state_size = nest.flatten(state_size)

  if not initializers:
    flat_initializer = tuple(tf.zeros_initializer() for _ in flat_state_size)
  else:
    nest.assert_same_structure(initializers, state_size)
    flat_initializer = nest.flatten(initializers)
    if not all([callable(init) for init in flat_initializer]):
      raise ValueError("Not all the passed initializers are callable objects.")

  if not regularizers:
    flat_regularizer = tuple({} for _ in flat_state_size)
  else:
    nest.assert_same_structure(regularizers, state_size)
    flat_regularizer = nest.flatten(regularizers)
    if not all([callable(regularizer) for regularizer in flat_regularizer]):
      raise ValueError("Not all the passed regularizers are callable objects.")

  # Produce names for the variables. In the case of a tuple or nested tuple,
  # this is just a sequence of numbers, but for a flat `namedtuple`, we use
  # the field names. NOTE: this could be extended to nested `namedtuple`s,
  # but for now that's extra complexity that's not used anywhere.
  name_prefix = name or "initial_state"
  try:
    name_suffixes = [
        state_size._fields[i] for i in xrange(len(flat_state_size))]
  except (AttributeError, IndexError):
    name_suffixes = range(len(flat_state_size))

  flat_initial_state = []

  for name_suffix, size, init, regularizer in zip(
      name_suffixes, flat_state_size, flat_initializer, flat_regularizer):
    shape_with_batch_dim = [1] + tf.TensorShape(size).as_list()

    variable_name = "{}_{}".format(name_prefix, name_suffix)
    initial_state_module = basic.TrainableVariable(
        shape_with_batch_dim, dtype=dtype, initializers={"w": init},
        regularizers={"w": regularizer}, name=variable_name)
    initial_state_variable = initial_state_module()

    tiled_name = "state_{}_tiled".format(name_suffix)

    initial_state_variable_dims = initial_state_variable.get_shape().ndims
    tile_dims = [batch_size] + [1] * (initial_state_variable_dims - 1)
    flat_initial_state.append(
        tf.tile(initial_state_variable, tile_dims, name=tiled_name))

  return nest.pack_sequence_as(structure=state_size,
                               flat_sequence=flat_initial_state)