def METHOD_NAME(element_length_func, bucket_boundaries,
                                    batch_size):
  """Groups dataset records into batches by sequence length.
  Args:
    element_length_func: A function mapping a nested structure of tensors to a
      scalar `tf.int64` (sequence length).
    bucket_boundaries: Array of integers defining the sequence length boundaries
      to use for bucketing.
    batch_size: `int`, batch size to apply to length buckets.
  Returns:
    `tf.data.Dataset` object.
  """
  def _element_to_bucket_id(*args):
    """Maps record to bucket id based on sequence length."""
    seq_length = element_length_func(*args)
    boundaries = list(bucket_boundaries)
    buckets_min = [np.iinfo(np.int64).min] + boundaries
    buckets_max = boundaries + [np.iinfo(np.int64).max]
    conditions_c = tf.logical_and(
        tf.less_equal(buckets_min, seq_length),
        tf.less(seq_length, buckets_max))
    return tf.reduce_min(tf.where(conditions_c))
  def _reduce_func(bucket_id, grouped_dataset):
    """Applies non-padded batching to grouped dataset."""
    del bucket_id
    return grouped_dataset.batch(batch_size)
  return tf.contrib.data.group_by_window(
      key_func=_element_to_bucket_id,
      reduce_func=_reduce_func,
      window_size=batch_size,
      window_size_func=None)