code: def gather_faces(
      vertices: type_alias.TensorLike,
      indices: type_alias.TensorLike,
      name: str = "normals_gather_faces",
  ) -> type_alias.TensorLike:
      """Gather corresponding vertices for each face.
  
      Note:
        In the following, A1 to An are optional batch dimensions.
  
      Args:
        vertices: A tensor of shape `[A1, ..., An, V, D]`, where `V` is the number
          of vertices and `D` the dimensionality of each vertex. The rank of this
          tensor should be at least 2.
        indices: A tensor of shape `[A1, ..., An, F, M]`, where `F` is the number of
          faces, and `M` is the number of vertices per face. The rank of this tensor
          should be at least 2.
        name: A name for this op. Defaults to "normals_gather_faces".
  
      Returns:
        A tensor of shape `[A1, ..., An, F, M, D]` containing the vertices of each
        face.
  
      Raises:
        ValueError: If the shape of `vertices` or `indices` is not supported.
      """
      with tf.name_scope(name):
          vertices = tf.convert_to_tensor(value=vertices)
          indices = tf.convert_to_tensor(value=indices)
  
          shape.check_static(
              tensor=vertices,
              tensor_name="vertices",
              has_rank_greater_than=1,
          )
          shape.check_static(
              tensor=indices,
              tensor_name="indices",
              has_rank_greater_than=1,
          )
          shape.compare_batch_dimensions(
              tensors=(vertices, indices),
              last_axes=(-3, -3),
              broadcast_compatible=False,
          )
  
          if hasattr(tf, "batch_gather"):
              expanded_vertices = tf.expand_dims(vertices, axis=-3)
              broadcasted_shape = tf.concat(
                  [
                      tf.shape(input=indices)[:-1],
                      tf.shape(input=vertices)[-2:],
                  ],
                  axis=-1,
              )
              broadcasted_vertices = tf.broadcast_to(
                  expanded_vertices, broadcasted_shape
              )
              return tf.gather(
                  broadcasted_vertices, indices, batch_dims=-1
              )
          else:
              return tf.gather(
                  vertices,
                  indices,
                  axis=-2,
                  batch_dims=indices.shape.ndims - 2,
              )
  
file_path: graphics/tensorflow_graphics/geometry/representation/mesh/normals.py
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import numpy
  from six.moves import range
  import tensorflow
  from tensorflow_graphics.geometry.representation import triangle
  from tensorflow_graphics.util import export_api
  from tensorflow_graphics.util import safe_ops
  from tensorflow_graphics.util import shape
  from tensorflow_graphics.util import type_alias
label_desc: Use image node_id 1 for calling a global function with example usage: gather_faces(vertices, indices, name) and returns: tf, tf