Get top 5 students for each class in many-to-many relationship
Student with GPAs is an aggregation
Class information is not an aggregation

Solution:

Use two queries
Query the GPAs (CTE and Window Function)
Query the class information

You will probably need two indices on student_id and class_id to boost the performance.
Example queries in MySQL 8.0.20:
WITH ordered_gpa AS(
    SELECT students.id,
        students.gpa, 
        student_class_rel.class_id,
        rank() over (partition by student_class_rel.class_id order by students.gpa DESC) gpa_rank
    FROM student_class_rel
    INNER JOIN students 
    ON student_class_rel.stu_id = students.id
)
SELECT * 
FROM ordered_gpa
WHERE gpa_rank &lt;= 5;

Here, we use Windows rather than GROUP BY, which is the PARTITION BY to split the rows.
SELECT class_id, name, room
FROM classes
WHERE class_id IN (
  SELECT DISTINCT class_id
  FROM student_class_rel
) tmp;

You could combine this query with the first one.