code: def shuffle_and_batch_data(dataset,
                             target_names,
                             features_info,
                             training,
                             num_devices,
                             shuffle_buffer_size=1024,
                             preprocess_fun=no_preprocess):
    
    def append_targets(example):
      """Append targets to the example dictionary. Needed for Keras."""
      if len(target_names) == 1:
        return (example, example[target_names[0]])
      targets = {}
      for name in target_names:
        targets[name] = example[name]
      return (example, targets)
    dataset = dataset.map(append_targets)
    if training:
      dataset = dataset.repeat()
      # Skip a random fraction at the beginning of the stream.  The skip is
      # essential for synchronous highly-parallel training to avoid multiple
      # replicas reading the same data in lock-step.
      dataset = dataset.skip(random.randint(0, _MAX_SKIP_EXAMPLES))
    dataset = preprocess_fun(dataset, training)
    shapes = {k: features_info[k].shape for k in features_info}
    shapes = (shapes, shapes[target_names[0]])
    dataset = dataset.shuffle(shuffle_buffer_size)
    dataset = batch_fun(dataset, training, shapes, target_names, num_devices)
    return dataset.prefetch(2)
docs: Shuffle and batch the given dataset.