def _rnn_step(time, sequence_length, min_sequence_length, max_sequence_length, zero_output, state, call_cell, state_size, skip_conditionals=False):
    "Calculate one step of a dynamic RNN minibatch.\n\n  Returns an (output, state) pair conditioned on the sequence_lengths.\n  When skip_conditionals=False, the pseudocode is something like:\n\n  if t >= max_sequence_length:\n    return (zero_output, state)\n  if t < min_sequence_length:\n    return call_cell()\n\n  # Selectively output zeros or output, old state or new state depending\n  # on if we've finished calculating each row.\n  new_output, new_state = call_cell()\n  final_output = np.vstack([\n    zero_output if time >= sequence_lengths[r] else new_output_r\n    for r, new_output_r in enumerate(new_output)\n  ])\n  final_state = np.vstack([\n    state[r] if time >= sequence_lengths[r] else new_state_r\n    for r, new_state_r in enumerate(new_state)\n  ])\n  return (final_output, final_state)\n\n  Args:\n    time: Python int, the current time step\n    sequence_length: int32 `Tensor` vector of size [batch_size]\n    min_sequence_length: int32 `Tensor` scalar, min of sequence_length\n    max_sequence_length: int32 `Tensor` scalar, max of sequence_length\n    zero_output: `Tensor` vector of shape [output_size]\n    state: Either a single `Tensor` matrix of shape `[batch_size, state_size]`,\n      or a list/tuple of such tensors.\n    call_cell: lambda returning tuple of (new_output, new_state) where\n      new_output is a `Tensor` matrix of shape `[batch_size, output_size]`.\n      new_state is a `Tensor` matrix of shape `[batch_size, state_size]`.\n    state_size: The `cell.state_size` associated with the state.\n    skip_conditionals: Python bool, whether to skip using the conditional\n      calculations.  This is useful for `dynamic_rnn`, where the input tensor\n      matches `max_sequence_length`, and using conditionals just slows\n      everything down.\n\n  Returns:\n    A tuple of (`final_output`, `final_state`) as given by the pseudocode above:\n      final_output is a `Tensor` matrix of shape [batch_size, output_size]\n      final_state is either a single `Tensor` matrix, or a tuple of such\n        matrices (matching length and shapes of input `state`).\n\n  Raises:\n    ValueError: If the cell returns a state tuple whose length does not match\n      that returned by `state_size`.\n  "
    flat_state = nest.flatten(state)
    flat_zero_output = nest.flatten(zero_output)

    def _copy_one_through(output, new_output):
        copy_cond = (time >= sequence_length)
        return _on_device((lambda : array_ops.where(copy_cond, output, new_output)), device=new_output.op.device)

    def _copy_some_through(flat_new_output, flat_new_state):
        flat_new_output = [_copy_one_through(zero_output, new_output) for (zero_output, new_output) in zip(flat_zero_output, flat_new_output)]
        flat_new_state = [_copy_one_through(state, new_state) for (state, new_state) in zip(flat_state, flat_new_state)]
        return (flat_new_output + flat_new_state)

    def _maybe_copy_some_through():
        'Run RNN step.  Pass through either no or some past state.'
        (new_output, new_state) = call_cell()
        nest.assert_same_structure(state, new_state)
        flat_new_state = nest.flatten(new_state)
        flat_new_output = nest.flatten(new_output)
        return control_flow_ops.cond((time < min_sequence_length), (lambda : (flat_new_output + flat_new_state)), (lambda : _copy_some_through(flat_new_output, flat_new_state)))
    if skip_conditionals:
        (new_output, new_state) = call_cell()
        nest.assert_same_structure(state, new_state)
        new_state = nest.flatten(new_state)
        new_output = nest.flatten(new_output)
        final_output_and_state = _copy_some_through(new_output, new_state)
    else:
        empty_update = (lambda : (flat_zero_output + flat_state))
        final_output_and_state = control_flow_ops.cond((time >= max_sequence_length), empty_update, _maybe_copy_some_through)
    if (len(final_output_and_state) != (len(flat_zero_output) + len(flat_state))):
        raise ValueError('Internal error: state and output were not concatenated correctly.')
    final_output = final_output_and_state[:len(flat_zero_output)]
    final_state = final_output_and_state[len(flat_zero_output):]
    for (output, flat_output) in zip(final_output, flat_zero_output):
        output.set_shape(flat_output.get_shape())
    for (substate, flat_substate) in zip(final_state, flat_state):
        substate.set_shape(flat_substate.get_shape())
    final_output = nest.pack_sequence_as(structure=zero_output, flat_sequence=final_output)
    final_state = nest.pack_sequence_as(structure=state, flat_sequence=final_state)
    return (final_output, final_state)
Calculate one step of a dynamic RNN minibatch.

Returns an (output, state) pair conditioned on the sequence_lengths.
When skip_conditionals=False, the pseudocode is something like:

if t >= max_sequence_length:
  return (zero_output, state)
if t < min_sequence_length:
  return call_cell()

# Selectively output zeros or output, old state or new state depending
# on if we've finished calculating each row.
new_output, new_state = call_cell()
final_output = np.vstack([
  zero_output if time >= sequence_lengths[r] else new_output_r
  for r, new_output_r in enumerate(new_output)
])
final_state = np.vstack([
  state[r] if time >= sequence_lengths[r] else new_state_r
  for r, new_state_r in enumerate(new_state)
])
return (final_output, final_state)

Args:
  time: Python int, the current time step
  sequence_length: int32 `Tensor` vector of size [batch_size]
  min_sequence_length: int32 `Tensor` scalar, min of sequence_length
  max_sequence_length: int32 `Tensor` scalar, max of sequence_length
  zero_output: `Tensor` vector of shape [output_size]
  state: Either a single `Tensor` matrix of shape `[batch_size, state_size]`,
    or a list/tuple of such tensors.
  call_cell: lambda returning tuple of (new_output, new_state) where
    new_output is a `Tensor` matrix of shape `[batch_size, output_size]`.
    new_state is a `Tensor` matrix of shape `[batch_size, state_size]`.
  state_size: The `cell.state_size` associated with the state.
  skip_conditionals: Python bool, whether to skip using the conditional
    calculations.  This is useful for `dynamic_rnn`, where the input tensor
    matches `max_sequence_length`, and using conditionals just slows
    everything down.

Returns:
  A tuple of (`final_output`, `final_state`) as given by the pseudocode above:
    final_output is a `Tensor` matrix of shape [batch_size, output_size]
    final_state is either a single `Tensor` matrix, or a tuple of such
      matrices (matching length and shapes of input `state`).

Raises:
  ValueError: If the cell returns a state tuple whose length does not match
    that returned by `state_size`.
def _rnn_step(time, sequence_length, min_sequence_length, max_sequence_length, zero_output, state, call_cell, state_size, skip_conditionals=False):
    "Calculate one step of a dynamic RNN minibatch.\n\n  Returns an (output, state) pair conditioned on the sequence_lengths.\n  When skip_conditionals=False, the pseudocode is something like:\n\n  if t >= max_sequence_length:\n    return (zero_output, state)\n  if t < min_sequence_length:\n    return call_cell()\n\n  # Selectively output zeros or output, old state or new state depending\n  # on if we've finished calculating each row.\n  new_output, new_state = call_cell()\n  final_output = np.vstack([\n    zero_output if time >= sequence_lengths[r] else new_output_r\n    for r, new_output_r in enumerate(new_output)\n  ])\n  final_state = np.vstack([\n    state[r] if time >= sequence_lengths[r] else new_state_r\n    for r, new_state_r in enumerate(new_state)\n  ])\n  return (final_output, final_state)\n\n  Args:\n    time: Python int, the current time step\n    sequence_length: int32 `Tensor` vector of size [batch_size]\n    min_sequence_length: int32 `Tensor` scalar, min of sequence_length\n    max_sequence_length: int32 `Tensor` scalar, max of sequence_length\n    zero_output: `Tensor` vector of shape [output_size]\n    state: Either a single `Tensor` matrix of shape `[batch_size, state_size]`,\n      or a list/tuple of such tensors.\n    call_cell: lambda returning tuple of (new_output, new_state) where\n      new_output is a `Tensor` matrix of shape `[batch_size, output_size]`.\n      new_state is a `Tensor` matrix of shape `[batch_size, state_size]`.\n    state_size: The `cell.state_size` associated with the state.\n    skip_conditionals: Python bool, whether to skip using the conditional\n      calculations.  This is useful for `dynamic_rnn`, where the input tensor\n      matches `max_sequence_length`, and using conditionals just slows\n      everything down.\n\n  Returns:\n    A tuple of (`final_output`, `final_state`) as given by the pseudocode above:\n      final_output is a `Tensor` matrix of shape [batch_size, output_size]\n      final_state is either a single `Tensor` matrix, or a tuple of such\n        matrices (matching length and shapes of input `state`).\n\n  Raises:\n    ValueError: If the cell returns a state tuple whose length does not match\n      that returned by `state_size`.\n  "
    flat_state = nest.flatten(state)
    flat_zero_output = nest.flatten(zero_output)

    def _copy_one_through(output, new_output):
        copy_cond = (time >= sequence_length)
        return _on_device((lambda : array_ops.where(copy_cond, output, new_output)), device=new_output.op.device)

    def _copy_some_through(flat_new_output, flat_new_state):
        flat_new_output = [_copy_one_through(zero_output, new_output) for (zero_output, new_output) in zip(flat_zero_output, flat_new_output)]
        flat_new_state = [_copy_one_through(state, new_state) for (state, new_state) in zip(flat_state, flat_new_state)]
        return (flat_new_output + flat_new_state)

    def _maybe_copy_some_through():
        'Run RNN step.  Pass through either no or some past state.'
        (new_output, new_state) = call_cell()
        nest.assert_same_structure(state, new_state)
        flat_new_state = nest.flatten(new_state)
        flat_new_output = nest.flatten(new_output)
        return control_flow_ops.cond((time < min_sequence_length), (lambda : (flat_new_output + flat_new_state)), (lambda : _copy_some_through(flat_new_output, flat_new_state)))
    if skip_conditionals:
        (new_output, new_state) = call_cell()
        nest.assert_same_structure(state, new_state)
        new_state = nest.flatten(new_state)
        new_output = nest.flatten(new_output)
        final_output_and_state = _copy_some_through(new_output, new_state)
    else:
        empty_update = (lambda : (flat_zero_output + flat_state))
        final_output_and_state = control_flow_ops.cond((time >= max_sequence_length), empty_update, _maybe_copy_some_through)
    if (len(final_output_and_state) != (len(flat_zero_output) + len(flat_state))):
        raise ValueError('Internal error: state and output were not concatenated correctly.')
    final_output = final_output_and_state[:len(flat_zero_output)]
    final_state = final_output_and_state[len(flat_zero_output):]
    for (output, flat_output) in zip(final_output, flat_zero_output):
        output.set_shape(flat_output.get_shape())
    for (substate, flat_substate) in zip(final_state, flat_state):
        substate.set_shape(flat_substate.get_shape())
    final_output = nest.pack_sequence_as(structure=zero_output, flat_sequence=final_output)
    final_state = nest.pack_sequence_as(structure=state, flat_sequence=final_state)
    return (final_output, final_state)