docs: def generate_name_variations(name):
      """Generate name variations for a given name.
  
      Args:
          name (six.text_type): The name whose variations are to be generated.
  
      Returns:
          list: All the name variations for the given name.
  
      Notes:
          Uses `unidecode` for doing unicode characters transliteration to ASCII ones. This was chosen so that we can map
          both full names of authors in HEP records and user's input to the same space and thus make exact queries work.
      """
      def _update_name_variations_with_product(set_a, set_b):
          name_variations.update([
              unidecode((names_variation[0] +
                         separator +
                         names_variation[1]).strip(''.join(_LASTNAME_NON_LASTNAME_SEPARATORS))).lower()
              for names_variation
              in product(set_a, set_b)
              for separator
              in _LASTNAME_NON_LASTNAME_SEPARATORS
          ])
  
      parsed_name = ParsedName.loads(name)
  
      # Handle rare-case of single-name
      if len(parsed_name) == 1:
          return [parsed_name.dumps().lower()]
  
      name_variations = set()
  
      # We need to filter out empty entries, since HumanName for this name `Perelstein,, Maxim` returns a first_list with
      # an empty string element.
      non_lastnames = [
          non_lastname
          for non_lastname
          in parsed_name.first_list + parsed_name.suffix_list
          if non_lastname
      ]
  
      # This is needed because due to erroneous data (e.g. having many authors in a single authors field) ends up
      # requiring a lot of memory (due to combinatorial expansion of all non lastnames).
      # The policy is to use the input as a name variation, since this data will have to be curated.
      if len(non_lastnames) > _NAMES_MAX_NUMBER_THRESHOLD or len(parsed_name.last_list) > _NAMES_MAX_NUMBER_THRESHOLD:
          LOGGER.error('Skipping name variations generation - too many names in: "%s"', name)
          return [name]
  
      non_lastnames_variations = \
          _generate_non_lastnames_variations(non_lastnames)
      lastnames_variations = _generate_lastnames_variations(parsed_name.last_list)
  
      # Create variations where lastnames comes first and is separated from non lastnames either by space or comma.
      _update_name_variations_with_product(lastnames_variations, non_lastnames_variations)
  
      # Second part of transformations - having the lastnames in the end.
      _update_name_variations_with_product(non_lastnames_variations, lastnames_variations)
  
      return list(name_variations)