code: def fromTFExample(iter, binary_features=[]):
    
    # convert from protobuf-like dict to DataFrame-friendly dict
    def _get_value(k, v):
      if v.int64_list.value:
        result = v.int64_list.value
      elif v.float_list.value:
        result = v.float_list.value
      else:  # string or bytearray
        if k in binary_features:
          return bytearray(v.bytes_list.value[0])
        else:
          return v.bytes_list.value[0].decode('utf-8')
  
      if len(result) > 1:         # represent multi-item tensors as python lists
        return list(result)
      elif len(result) == 1:      # extract scalars from single-item tensors
        return result[0]
      else:                       # represent empty tensors as python None
        return None
  
    results = []
    for record in iter:
      example = tf.train.Example()
      example.ParseFromString(bytes(record[0]))       # record is (bytestr, None)
      d = {k: _get_value(k, v) for k, v in sorted(example.features.feature.items())}
      row = Row(**d)
      results.append(row)
  
    return results
docs: mapPartition function to convert an RDD of serialized tf.train.Example bytestring into an RDD of Row.
  
    Note: TensorFlow represents both strings and binary types as tf.train.BytesList, and we need to
    disambiguate these types for Spark DataFrames DTypes (StringType and BinaryType), so we require a "hint"
    from the caller in the ``binary_features`` argument.
  
    Args:
      :iter: the RDD partition iterator
      :binary_features: a list of tf.train.Example features which are expected to be binary/bytearrays.
  
    Returns:
      An array/iterator of DataFrame Row with features converted into columns.