Querying all items that are in a many-to-many relationship with a child of an object
I also considered trying something like
return Images.objects.filter(articles__publication=self) 

But I don't think that I can do this because then I have to define Images above
Publications, which won't work with Articles and Images.

Did you try this?  It seems like it would work and would be the best approach.  You could add a .distinct() clause at the end of the query to avoid converting to a set.
It is best practice to set the related_name and related_query_name variables on your model related fields.  This will make your queries less verbose; article_set and image_set become articles and images, respectively.  See example below
class Article(models.Model):
    filename = models.CharField(max_length=255)
    publication = models.ForeignKey(to=Publication,
                                    on_delete=models.CASCADE,
                                    related_name='articles',
                                    related_query_name='article')


class Image(models.Model):
    name = models.CharField(max_length=255)
    articles = models.ManyToManyField(to=Article,
                                      related_name='images',
                                      related_query_name='image')

Look at the prefetch_related documentation.  You are querying the db for every image set on each article.
@property
def images(self):
    images = []
    for article in self.article_set.all():
        images += list(article.images.all())
    return list(set(images))

Using prefetch_related:
@property
def images(self):
    images = []
    publication = self.objects.prefetch_related('articles__images')
    for article in publication.articles.all():
        for image in article.images.all():
            images.append(image)

    return set(images)