//  [python]
def __call__(self, inputs, state, scope=None, debug=False):
    """Unroll the memory augmented cell for one step.

    Args:
      inputs: (Possibly nested tuple of) Tensor, the input at this time step.
      state: An instance of MemoryStateTuple containing tensors from the
        previous time step.
    """
    # B is batch size.

    # 1) Use read_ind to find memory location to read from
    # as input.

    # inputs.read_ind: (B, 1)
    # memory: (B, mem_size, embed_size)
    read_ind = tf.cast(inputs.read_ind, tf.int32)
    batch_size = tf.shape(read_ind)[0]
    if debug:
      print('batch size is', batch_size)
      print('read ind is', read_ind)
    mem_ind = tf.range(batch_size)

    # read_mem_ind: (B, 1)
    read_mem_ind = tf.expand_dims(mem_ind, axis=1)
    # read_ind: (B, 2)
    read_ind = tf.concat([read_mem_ind, read_ind], axis=1)
    if debug:
      print('processed read ind is', read_ind)

    # inner_inputs: (B, embed_size)
    inner_inputs = tf.gather_nd(state.memory, read_ind)
    if debug:
      print('inner_inputs is', inner_inputs)

    inner_state = state.inner_state

    # 2) Run the inner RNNCell.

    # inner_outputs: (B, embed_size)
    cell_outputs, new_inner_state = self._cell(
        inner_inputs, inner_state, scope=scope)
    if self._use_score_wrapper:
      inner_outputs, score_val = cell_outputs
    else:
      inner_outputs = cell_outputs

    if debug:
      print('inner_outputs is', inner_outputs)

    # 3) Compute logits for valid indices (using logit_masks
    # to mask out padded valid indices (-1)).

    # valid_indices: (B, max_n_valid_indices)
    valid_indices = tf.cast(inputs.valid_indices, tf.int32)
    if debug:
      print('valid_indices is', valid_indices)

    # Logit mask: (B, max_n_valid_indices)
    logit_masks = tf.greater_equal(inputs.valid_indices, 0)
    logit_masks = tf.cast(logit_masks, tf.float32)

    if debug:
      print('logit_masks is', logit_masks)

    # Normalize indices to be at least 0.
    valid_indices = tf.maximum(valid_indices, 0)

    # valid_indices: (B, max_n_valid_indices, 1)
    valid_indices = tf.expand_dims(valid_indices, -1)
    if debug:
      print('valid_indices is', valid_indices)
      print('mem_ind is', mem_ind)

    valid_mem_ind = tf.expand_dims(mem_ind, axis=1)

    # valid_mem_ind: (B, 1, 1)
    valid_mem_ind = tf.expand_dims(valid_mem_ind, axis=2)
    if debug:
      print('valid_mem_ind is', valid_mem_ind)

    # valid_mem_ind: (B, max_n_valid_indices, 1)
    valid_mem_ind = tf.tile(valid_mem_ind, [1, self._max_n_valid_indices, 1])

    # valid_indices: (B, max_n_valid_indices, 2)
    # Third dimension of valid_indices is [b_i, valid_index] so that it can
    # index into the right memory location.
    valid_indices = tf.concat([valid_mem_ind, valid_indices], axis=2)

    if debug:
      print('valid_indices is', valid_indices)

    # select all the valid slots.
    # valid_values: (B, max_n_valid_indices, embed_size)
    valid_values = tf.gather_nd(state.memory, valid_indices)
    if debug:
      print('valid_values is', valid_values)

    # expanded_inner_outputs: (B, 1, embed_size)
    expanded_inner_outputs = tf.expand_dims(inner_outputs, 1)
    if debug:
      print('expanded_inner_outputs is', expanded_inner_outputs)

    # valid_values: (B, embed_size, max_n_valid_indices)
    valid_values = tf.transpose(valid_values, [0, 2, 1])
    if debug:
      print('valid_values is', valid_values)

    # logits: (B, 1, max_n_valid_indices)
    logits = tf.matmul(expanded_inner_outputs, valid_values)

    if debug:
      print('logits is', logits)

    # logits: (B, max_n_valid_indices)
    logits = tf.squeeze(logits, axis=[1])
    if debug:
      print('logits is', logits)

    # masked_logits = (logits * logit_masks) - (1 - logit_masks) * 1e6
    masked_logits = logits * logit_masks + (1 - logit_masks) * tf.float32.min
    # masked_logits = tf.Print(masked_logits, [masked_logits],
    # message='masked_logits')

    outputs = masked_logits
    # 4) Write the output of the inner RNN to a memory
    # location (write_ind), using write_masks to mask out
    # padded write_ind (-1).

    # write_ind: (B, 1)
    write_ind = tf.cast(inputs.write_ind, tf.int32)
    if debug:
      print('write_ind is', write_ind)

    # write mask: (B, 1)
    write_masks = tf.greater_equal(inputs.write_ind, 0)
    if debug:
      print('write_masks greater_equal', write_masks)

    write_masks = tf.cast(write_masks, tf.float32)

    # write mask: (B, 1, 1)
    write_masks = tf.expand_dims(write_masks, [-1])

    if debug:
      print('write_masks is', write_masks)

    # Normalize write_ind to be above 0.
    # write_ind: (B, 1)
    write_ind = tf.maximum(write_ind, 0)

    # write_mem_ind: (B, 1)
    write_mem_ind = tf.expand_dims(mem_ind, axis=1)

    # write_ind: (B, 2)
    # Second dimension is [b_i, write_index]
    write_ind = tf.concat([write_mem_ind, write_ind], axis=1)
    if debug:
      print('write_ind is', write_ind)

    if debug:
      print('masked_logits is', masked_logits)
      print('memory is', state.memory)

    # write_mat: (B, mem_size, embed_size)
    write_mat = tf.scatter_nd(
        write_ind, inner_outputs, shape=tf.shape(state.memory))

    if debug:
      print('@' * 50)
      print('write_mat is', write_mat)
      print('write_mask is', write_masks)
      print('@' * 50)

    masked_write_mat = write_mat * write_masks
    new_memory = state.memory + masked_write_mat

    state = MemoryStateTuple(new_memory, new_inner_state)
    if debug:
      print('state is', state)

    if self._use_score_wrapper:
      outputs = (outputs, score_val)
    return (outputs, state)