docs: async def _send_album(self, entity, files, caption='',
                            progress_callback=None, reply_to=None,
                            parse_mode=(), silent=None):
          """Specialized version of .send_file for albums"""
          # We don't care if the user wants to avoid cache, we will use it
          # anyway. Why? The cached version will be exactly the same thing
          # we need to produce right now to send albums (uploadMedia), and
          # cache only makes a difference for documents where the user may
          # want the attributes used on them to change.
          #
          # In theory documents can be sent inside the albums but they appear
          # as different messages (not inside the album), and the logic to set
          # the attributes/avoid cache is already written in .send_file().
          entity = await self.get_input_entity(entity)
          if not utils.is_list_like(caption):
              caption = (caption,)
  
          captions = []
          for c in reversed(caption):  # Pop from the end (so reverse)
              captions.append(await self._parse_message_text(c or '', parse_mode))
  
          reply_to = utils.get_message_id(reply_to)
  
          # Need to upload the media first, but only if they're not cached yet
          media = []
          for file in files:
              # Albums want :tl:`InputMedia` which, in theory, includes
              # :tl:`InputMediaUploadedPhoto`. However using that will
              # make it `raise MediaInvalidError`, so we need to upload
              # it as media and then convert that to :tl:`InputMediaPhoto`.
              fh, fm, _ = await self._file_to_media(file)
              if isinstance(fm, types.InputMediaUploadedPhoto):
                  r = await self(functions.messages.UploadMediaRequest(
                      entity, media=fm
                  ))
                  self.session.cache_file(
                      fh.md5, fh.size, utils.get_input_photo(r.photo))
  
                  fm = utils.get_input_media(r.photo)
  
              if captions:
                  caption, msg_entities = captions.pop()
              else:
                  caption, msg_entities = '', None
              media.append(types.InputSingleMedia(
                  fm,
                  message=caption,
                  entities=msg_entities
              ))
  
          # Now we can construct the multi-media request
          result = await self(functions.messages.SendMultiMediaRequest(
              entity, reply_to_msg_id=reply_to, multi_media=media, silent=silent
          ))
  
          # We never sent a `random_id` for the messages that resulted from
          # the request so we can't pair them up with the `Updates` that we
          # get from Telegram. However, the sent messages have a photo and
          # the photo IDs match with those we did send.
          #
          # Updates -> {_: message}
          messages = self._get_response_message(None, result, entity)
          # {_: message} -> {photo ID: message}
          messages = {m.photo.id: m for m in messages.values()}
          # Sent photo IDs -> messages
          return [messages[m.media.id.id] for m in media]