//  [python]
def decode_one_step(step, live_beams, eos_positions,
                    compute_logits,
                    beam_log_probs, batch_size, beam_size,
                    features, areas, hparams,
                    use_cache, cache,
                    mode=tf_estimator.ModeKeys.EVAL,
                    always_consumed=True):
  """decode one step."""
  # features: [batch_size * beam_size, step + 1, ...]
  # [batch_size * beam_size, num_areas]
  action_logits, object_logits, consumed_logits, references = compute_logits(
      features, hparams, mode, use_cache, cache)
  input_logits = references["input_logits"]
  verb_area_logits = references["verb_area_logits"]
  obj_area_logits = references["obj_area_logits"]
  input_area_logits = references["input_area_logits"]
  cache = {}
  cache["input_logits"] = input_logits
  cache["verb_area_logits"] = verb_area_logits
  cache["obj_area_logits"] = obj_area_logits
  cache["input_area_logits"] = input_area_logits
  # step + 1
  input_length = tf.shape(features["verb_refs"])[1]
  output_length = tf.shape(verb_area_logits)[1]
  with tf.control_dependencies([
      tf.assert_equal(input_length, output_length)]):
    # Decode consumed
    beam_log_probs, is_ref_consumed = _advance(
        step,
        beam_log_probs,
        previous_refs=None,
        area_logits=consumed_logits[:, -1, :], areas=None,
        batch_size=batch_size, beam_size=beam_size, append_refs=False,
        condition=tf.cast(live_beams, tf.int32))
    if always_consumed:
      use_cache = tf.zeros_like(use_cache)
    else:
      use_cache = 1 - is_ref_consumed
    # Decode actions and objects greedy
    _, action = tf.nn.top_k(action_logits[:, -1, :])
    features["verbs"] = tf.concat([
        features["verbs"][:, :step],
        action, features["verbs"][:, step + 1:]], axis=1)
    features["verbs"] = tf.where(tf.equal(use_cache, 1),
                                 # Emit CLICK (2) if not consumed
                                 tf.fill(tf.shape(features["verbs"]), 2),
                                 features["verbs"])
    _, obj = tf.nn.top_k(object_logits[:, -1, :])
    features["objects"] = tf.concat([
        features["objects"][:, :step],
        obj, features["objects"][:, step + 1:]], axis=1)
    # Decode verb refs
    beam_log_probs, new_refs = _advance(
        step,
        beam_log_probs,
        previous_refs=features["verb_refs"][:, :-1, :],
        area_logits=verb_area_logits[:, -1, :], areas=areas,
        batch_size=batch_size, beam_size=beam_size,
        condition=tf.cast(live_beams, tf.int32))
    features["verb_refs"] = new_refs
    live_beams = tf.logical_and(
        live_beams,
        tf.not_equal(new_refs[:, -1, 0], eos_positions))
    # Decode object refs
    beam_log_probs, new_refs = _advance(
        step,
        beam_log_probs,
        previous_refs=features["obj_refs"][:, :-1, :],
        area_logits=obj_area_logits[:, -1, :], areas=areas,
        batch_size=batch_size, beam_size=beam_size,
        condition=tf.cast(live_beams, tf.int32))
    features["obj_refs"] = new_refs
    # Decode input refs
    beam_log_probs, need_inputs = _advance(
        step,
        beam_log_probs,
        previous_refs=None,
        area_logits=input_logits[:, -1, :], areas=None,
        batch_size=batch_size, beam_size=beam_size, append_refs=False,
        condition=tf.cast(live_beams, tf.int32))
    beam_log_probs, new_refs = _advance(
        step,
        beam_log_probs,
        previous_refs=features["input_refs"][:, :-1, :],
        area_logits=input_area_logits[:, -1, :], areas=areas,
        batch_size=batch_size, beam_size=beam_size,
        condition=tf.cast(live_beams, tf.int32) * need_inputs)
    features["input_refs"] = new_refs
    return beam_log_probs, live_beams, use_cache, cache