Specialized version of .send_file for albums

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]